package com.jigoucai.module;

import com.jigoucai.bean.biz.AuthCode;
import com.jigoucai.bean.param.biz.MLogin;
import com.jigoucai.bean.param.biz.UserInfo;
import com.jigoucai.bean.param.req.user.*;
import com.jigoucai.bean.param.resp.BaseResp;
import com.jigoucai.entity.user.Account;
import com.jigoucai.entity.user.User;
import com.jigoucai.service.JedisService;
import com.jigoucai.util.Code;
import com.jigoucai.util.JgcUtil;
import com.jigoucai.util.Util;
import com.qcloud.param.biz.Tel;
import com.qcloud.param.req.SendsmsReq;
import com.qcloud.param.resp.SendsmsResp;
import com.qcloud.util.SendUtil;
import org.nutz.dao.Cnd;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
import org.nutz.json.JsonFormat;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.Times;
import org.nutz.lang.random.R;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.Mvcs;
import org.nutz.mvc.adaptor.JsonAdaptor;
import org.nutz.mvc.annotation.*;
import org.nutz.weixin.bean.sns.biz.PhoneDecryptionData;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * Created by Jianghao on 2018/3/13
 *
 * @howechiang
 */
@IocBean
@Fail("http:500")
@At("/user")
public class UserModule extends BaseModule {

    @Inject("java:$conf.get('qcloud.sms.sdkAppID')")
    protected String QCLOUD_SMS_SDKAPPID;
    @Inject("java:$conf.get('qcloud.sms.appKey')")
    protected String QCLOUD_SMS_APPKEY;
    @Inject("java:$conf.get('qcloud.sms.loginTplId')")
    protected int QCLOUD_SMS_LOGINTPLID;
    @Inject("java:$conf.get('qcloud.sms.tplId')")
    protected int QCLOUD_SMS_TPLID;
    @Inject("java:$conf.get('qcloud.sms.PaypasswordTplId')")
    protected int QCLOUD_SMS_PAYPASSWORDTPLID;

    /**
     * 验证支付密码
     *
     * @param req
     * @return
     */
    @POST
    @At("/checkPayPswd")
    @Ok("json:full")
    @AdaptBy(type = JsonAdaptor.class)
    public BaseResp checkPayPswd(CheckPayPayPswdReq req) {
        try {
            if (Strings.isBlank(req.getPayPassword())) {
                return Code.resp("USER_PARAMTER_MISSING", "支付密码");
            } else {
                User user = userService.fetch(req.getUserId());
                if (Strings.equalsIgnoreCase(user.getPayPassword(), Lang.sha1(req.getUserId() + req.getPayPassword()))) {
                    return JgcUtil.buildSuccessResp("");
                } else {
                    return Code.resp("USER_PAYPASSWORD_IS_ERROR");
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Code.resp("SYS_ERROR");
        }
    }

    /**
     * 验证保证金是否够接单
     *
     * @param req
     * @return
     */
    @POST
    @At("/checkMargin")
    @Ok("json:full")
    @AdaptBy(type = JsonAdaptor.class)
    public BaseResp checkMargin(CheckMarginReq req) {
        try {
            if (req.getMargin() < 1) {
                return Code.resp("USER_PARAMTER_MISSING", "保证金");
            } else {
                if (financeService.getMargin(req.getUserId()) < req.getMargin()) {
                    return Code.resp("USER_MARGIN_INSUFFICIENT");
                } else {
                    return JgcUtil.buildSuccessResp("");
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Code.resp("SYS_ERROR");
        }
    }

    /**
     * 获取用户信息
     *
     * @param req
     * @return
     */
    @POST
    @At("/getUserInfo")
    @Ok("json:full")
    @AdaptBy(type = JsonAdaptor.class)
    public BaseResp getUserInfo(GetUserInfoReq req) {
        try {
            User user = userService.fetch(req.getUserId());
            UserInfo info = new UserInfo(user);
            info.setMyFund(financeService.getFund(user.getUserId()));
            info.setMyMargin(financeService.getMargin(user.getUserId()));
            return JgcUtil.buildSuccessResp(info);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Code.resp("SYS_ERROR");
        }
    }

    /**
     * 发验证码
     *
     * @param req
     * @return
     */
    @POST
    @At("/sendCode")
    @Ok("json:full")
    @AdaptBy(type = JsonAdaptor.class)
    public BaseResp sendCode(SendCodeReq req) {
        try {
            if (Strings.isBlank(req.getTarget())) {
                return Code.resp("USER_PARAMTER_MISSING", "手机号码");
            } else if (Strings.isNotBlank(Util.checkCodeAction(req.getAction()))) {
                return Code.resp("USER_AUTHCODE_UNSUPPORTED_USE");
            } else {
                if (Strings.equalsIgnoreCase(req.getAction(), "BIND")) {
                    if (!Lang.isEmpty(dao.fetch(User.class, Cnd.where("mobile", "=", req.getTarget())))) {
                        return Code.resp("USER_MOBILE_BINDED");
                    }
                }
                AuthCode authCode = new AuthCode();
                authCode.setAction(req.getAction().toUpperCase());
                authCode.setTarget(req.getTarget());
                authCode.setCreateTime(Times.now());
                authCode.setExpireTime(Times.nextMinute(authCode.getCreateTime(), 5));
                authCode.setCode(R.captchaNumber(4));
                authCode.setUserId(req.getUserId());
                authCode.setStatus("SENT");
                authCode.setTargetType(req.getTargetType());
                System.out.println(authCode.toString());
                JedisService.set(buildAuthCodeRedisKey(authCode.getTarget(), authCode.getUserId(), authCode.getAction()), Json.toJson(authCode, JsonFormat.compact()), authCode.getExpireTime());
                SendsmsReq s = new SendsmsReq();
                s.setTel(new Tel(authCode.getTarget()));
                if (Strings.equalsIgnoreCase(req.getAction(), "LOGIN")) {
                    s.setTplId(QCLOUD_SMS_LOGINTPLID);
                } else {
                    s.setTplId(QCLOUD_SMS_TPLID);
                }
                if (!Lang.isEmpty(req.getUserId())) {
                    s.setExtend(req.getUserId() + "");
                }
                s.setTime(Times.getTS());
                s.setParams(new ArrayList<String>(Arrays.asList(authCode.getCode(), "5")));
                SendsmsResp resp = SendUtil.sendsms(QCLOUD_SMS_SDKAPPID, QCLOUD_SMS_APPKEY, s);
                if (Lang.equals(resp.getResult(), 0)) {
                    return JgcUtil.buildSuccessResp("验证码发送成功");
                } else {
                    return Code.resp("USER_AUTHCODE_SEND_ERROR", resp.getErrmsg());
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Code.resp("SYS_ERROR");
        }
    }

    protected String buildAuthCodeRedisKey(String target, Integer userId, String action) {
        StringBuffer sb = new StringBuffer("authCode:" + action);
        if (!Lang.isEmpty(userId)) {
            sb.append(":").append(userId);
        }
        if (Strings.isNotBlank(target)) {
            sb.append(":").append(target);
        }
        return "djp:user:" + sb.toString();
    }


    /**
     * 小程序登录
     *
     * @param req
     * @return
     */
    @POST
    @At("/mLogin")
    @Ok("json:full")
    @AdaptBy(type = JsonAdaptor.class)
    public BaseResp mLogin(MLoginReq req) {

        try {
            if (Strings.isBlank(req.getSource())) {
                return Code.resp("USER_PARAMTER_MISSING", "登录方式");
            } else if (Strings.isBlank(req.getCode())) {
                return Code.resp("USER_PARAMTER_MISSING", "用户登录凭证");
            } else {
                MLogin login = userService.mLogin(req, Mvcs.getReq());
                if (Lang.isEmpty(login)) {
                    return Code.resp("USER_IS_FROZEN");
                } else {
                    return JgcUtil.buildSuccessResp(Lang.obj2nutmap(login));
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Code.resp("SYS_ERROR");
        }
    }

    /**
     * 实名认证
     *
     * @param req
     * @return
     */
    @POST
    @At("/realnameAuth")
    @Ok("json:full")
    @AdaptBy(type = JsonAdaptor.class)
    public BaseResp realnameAuth(RealnameAuthReq req) {

        try {
            if (Strings.isBlank(req.getRealname())) {
                return Code.resp("USER_PARAMTER_MISSING", "真实姓名");
            } else if (Strings.isBlank(req.getIdCard())) {
                return Code.resp("USER_PARAMTER_MISSING", "身份证号码");
            } else {
                User user = dao.fetch(User.class, req.getUserId());
                if (user.isAuth()) {
                    return Code.resp("USER_HAS_BEEN_AUTHENTICATED");
                } else if (!Strings.isCitizenId(req.getIdCard())) {
                    return Code.resp("SYS_PARAMTER_FORMAT_ERROR", "身份证号码");
                } else if (!Util.isRealname(req.getRealname())) {
                    return Code.resp("SYS_PARAMTER_FORMAT_ERROR", "真实姓名");
                } else {
                    user.setAuth(true);
                    user.setRealname(req.getRealname());
                    user.setIdCard(req.getIdCard());
                    dao.update(user, "^(realname|idCard|isAuth)$");
                    return JgcUtil.buildSuccessResp("实名信息录入成功");
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Code.resp("SYS_ERROR");
        }
    }

    /**
     * 小程序绑定手机号码
     *
     * @param req
     * @return
     */
    @POST
    @At("/bindPhone")
    @Ok("json:full")
    @AdaptBy(type = JsonAdaptor.class)
    public BaseResp bindPhone(BindPhoneReq req) {

        try {
            if (Strings.isBlank(req.getMobile())) {
                return Code.resp("USER_PARAMTER_MISSING", "手机号码");
            } else if (Strings.isBlank(req.getAuthCode())) {
                return Code.resp("USER_PARAMTER_MISSING", "短信验证码");
            } else {
                User user = dao.fetch(User.class, Cnd.where("mobile", "=", req.getMobile()));
                if (!Lang.isEmpty(user)) {
                    return Code.resp("USER_MOBILE_ISUSED");
                }
                user = dao.fetch(User.class, req.getUserId());
                if (Lang.isEmpty(user)) {
                    return Code.resp("USER_NOT_FOUND");
                }
                if (Strings.isNotBlank(user.getMobile())) {
                    return Code.resp("USER_MOBILE_BINDED");
                }
                String json = JedisService.get(buildAuthCodeRedisKey(req.getMobile(), req.getUserId(), "BIND"));
                AuthCode authCode = Json.fromJson(AuthCode.class, json);
                if (!Strings.equalsIgnoreCase(authCode.getCode(), req.getAuthCode())) {
                    return Code.resp("USER_AUTHCODE_VALIDATION_ERROR");
                }
                user.setMobile(req.getMobile());
                String payPassword = R.captchaNumber(6);
                SendsmsReq s = new SendsmsReq();
                s.setTel(new Tel(authCode.getTarget()));
                s.setTplId(QCLOUD_SMS_PAYPASSWORDTPLID);
                s.setExtend(req.getUserId() + "");
                s.setTime(Times.getTS());
                s.setParams(new ArrayList<String>(Arrays.asList(payPassword)));
                SendUtil.sendsms(QCLOUD_SMS_SDKAPPID, QCLOUD_SMS_APPKEY, s);
                user.setPayPassword(Lang.sha1(user.getUserId() + Lang.md5(payPassword)));
                dao.update(user, "^(mobile|payPassword)$");
                JedisService.del(buildAuthCodeRedisKey(req.getMobile(), req.getUserId(), "BIND"));
                return JgcUtil.buildSuccessResp("手机号码绑定成功");
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Code.resp("SYS_ERROR");
        }
    }

    /**
     * 修改支付密码
     *
     * @param req
     * @return
     */
    @POST
    @At("/modifyPayPswd")
    @Ok("json:full")
    @AdaptBy(type = JsonAdaptor.class)
    public BaseResp modifyPayPswd(ModifyPayPswdReq req) {

        try {
            if (Strings.isBlank(req.getAuthCode())) {
                return Code.resp("USER_PARAMTER_MISSING", "短信验证码");
            } else {
                User user = dao.fetch(User.class, req.getUserId());
                if (Lang.isEmpty(user)) {
                    return Code.resp("USER_NOT_FOUND");
                }
                String json = JedisService.get(buildAuthCodeRedisKey(user.getMobile(), req.getUserId(), "MODIFY_PAY_PWD"));
                if (Strings.isBlank(json)) {
                    return Code.resp("USER_AUTHCODE_TIME_LIMIT");
                }
                AuthCode authCode = Json.fromJson(AuthCode.class, json);
                if (!Strings.equalsIgnoreCase(authCode.getCode(), req.getAuthCode())) {
                    return Code.resp("USER_AUTHCODE_VALIDATION_ERROR");
                }
                user.setPayPassword(Lang.sha1(user.getUserId() + req.getPayPassword()));
                dao.update(user, "^(payPassword)$");
                JedisService.del(buildAuthCodeRedisKey(null, req.getUserId(), "MODIFY_PAY_PWD"));
                return JgcUtil.buildSuccessResp("支付密码修改成功");
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Code.resp("SYS_ERROR");
        }
    }

    /**
     * 取提现账号
     *
     * @param req
     * @return
     */
    @POST
    @At("/getCashAccount")
    @Ok("json:full")
    @AdaptBy(type = JsonAdaptor.class)
    public BaseResp getCashAccount(GetCashAccountReq req) {

        try {
            User user = userService.fetch(req.getUserId());
            if (Lang.isEmpty(user)) {
                return Code.resp("USER_NOT_FOUND");
            }
            return JgcUtil.buildSuccessResp(new NutMap().setv("list", user.getCashAccounts()));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Code.resp("SYS_ERROR");
        }
    }

    /**
     * 取实名信息
     *
     * @param req
     * @return
     */
    @POST
    @At("/getAuth")
    @Ok("json:full")
    @AdaptBy(type = JsonAdaptor.class)
    public BaseResp getAuth(GetAuthReq req) {

        try {
            User user = userService.fetch(req.getUserId());
            if (Lang.isEmpty(user)) {
                return Code.resp("USER_NOT_FOUND");
            }
            if (user.isAuth()) {
                return JgcUtil.buildSuccessResp(new NutMap().setv("realname", user.getRealname().substring(0, 1) + "**").setv("idCard", user.getIdCard().substring(0, 5) + "*************").setv("isAuth", true));
            } else {
                return JgcUtil.buildSuccessResp(new NutMap().setv("realname", "").setv("idCard", "").setv("isAuth", false));
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Code.resp("SYS_ERROR");
        }
    }

    /**
     * 小程序绑定手机发送验证码
     *
     * @param req
     * @return
     */
    @POST
    @At("/sendCode4Miniapp")
    @Ok("json:full")
    @AdaptBy(type = JsonAdaptor.class)
    public BaseResp sendCode4Miniapp(SendCode4MiniappReq req) {

        try {
            if (Strings.isBlank(req.getEncryptedData())) {
                return Code.resp("USER_PARAMTER_MISSING", "解敏信息");
            } else if (Strings.isBlank(req.getIv())) {
                return Code.resp("USER_PARAMTER_MISSING", "算法位移值");
            } else {

                Account account = dao.fetch(Account.class, Cnd.where("userId", "=", req.getUserId()).and("source", "=", "MINIAPP"));
                if (Lang.isEmpty(account)) {
                    return Code.resp("USER_NOT_FOUND");
                }
                String json = org.nutz.weixin.util.Util.decryptionData(req.getEncryptedData(), account.getAccessToken(), req.getIv());
                if (Strings.isBlank(json)) {
                    return Code.resp("USER_GET_INFO_ERROR");
                }
                PhoneDecryptionData data = Json.fromJson(PhoneDecryptionData.class, json);
                User user = dao.fetch(User.class, Cnd.where("mobile", "=", data.getPurePhoneNumber()));
                if (!Lang.isEmpty(user)) {
                    return Code.resp("USER_MOBILE_ISUSED");
                }
                user = dao.fetch(User.class, req.getUserId());
                if (Strings.isNotBlank(user.getMobile())) {
                    return Code.resp("USER_MOBILE_BINDED");
                }
                AuthCode authCode = new AuthCode();
                authCode.setAction("BIND");
                authCode.setTarget(data.getPurePhoneNumber());
                authCode.setCreateTime(Times.now());
                authCode.setExpireTime(Times.nextMinute(authCode.getCreateTime(), 5));
                authCode.setCode(R.captchaNumber(4));
                authCode.setUserId(req.getUserId());
                authCode.setStatus("SENT");
                authCode.setTargetType("PHONE");
                System.out.println(authCode.toString());
                JedisService.set(buildAuthCodeRedisKey(authCode.getTarget(), authCode.getUserId(), authCode.getAction()), Json.toJson(authCode, JsonFormat.compact()), authCode.getExpireTime());
                SendsmsReq s = new SendsmsReq();
                s.setTel(new Tel(authCode.getTarget()));
                s.setTplId(QCLOUD_SMS_TPLID);
                if (!Lang.isEmpty(req.getUserId())) {
                    s.setExtend(req.getUserId() + "");
                }
                s.setTime(Times.getTS());
                s.setParams(new ArrayList<String>(Arrays.asList(authCode.getCode(), "5")));
                SendsmsResp resp = SendUtil.sendsms(QCLOUD_SMS_SDKAPPID, QCLOUD_SMS_APPKEY, s);
                if (Lang.equals(resp.getResult(), 0)) {
                    return JgcUtil.buildSuccessResp("验证码发送成功", new NutMap().setv("mobile", data.getPurePhoneNumber()));
                } else {
                    return Code.resp("USER_AUTHCODE_SEND_ERROR", resp.getErrmsg());
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Code.resp("SYS_ERROR");
        }
    }
}
